<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Routing\Route;
use Illuminate\Routing\Router;
use Spatie\Permission\Models\Permission;
use Spatie\Permission\Exceptions\PermissionAlreadyExists;

class UrlPermission extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'permission:url';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = '通过Route 生成 Perssion';


    protected $router;

    protected $headers = ['method', 'uri'];

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct(Router $router)
    {
        parent::__construct();
        $this->router = $router;
        $this->routes = $router->getRoutes();
    }

    /**
     * Execute the console command.
     *
     * @return mixed
     */
    public function handle()
    {
        $this->info("通过Rout url 生成权限");
        $routes = $this->getRoutes();
        $routes = collect($routes)->map(function ($route) {
            return $this->writeData($route);
        })->all();
        $routes =array_filter($routes);
        $this->info("writed ".\count($routes));
    }

    private function writeData($route)
    {

        try {
            Permission::create(['name' => $route['uri'], 'guard_name' => $route['uri']]);
            return true;
        } catch (PermissionAlreadyExists $e) {
            return false;
        }
    }

    /**
     * Compile the routes into a displayable format.
     *
     * @return array
     */
    protected function getRoutes()
    {
        $routes = collect($this->routes)->map(function ($route) {
            return $this->getRouteInformation($route);
        })->all();
        $routes = array_filter($routes);

        return array_filter($routes);
    }


    /**
     * Get the route information for a given route.
     *
     * @param  \Illuminate\Routing\Route $route
     * @return array
     */
    protected function getRouteInformation(Route $route)
    {
        $middlwate = $this->getMiddleware($route);

        if (!in_array('auth:api', $middlwate)) {
            return false;
        }

        $method = array_filter($route->methods(), function ($item) {
            if ($item == "POST" || $item == "GET") {
                return $item;
            }
            return false;
        });
        $uri = $this->uriClear($route->uri());

        return $this->filterRoute([
            'method' => implode('|', $method),
            'uri' => $uri,
            'middleware' => implode('|', $middlwate),
        ]);
    }


    private function uriClear($uri)
    {
        $uri = preg_replace('/\{.*\}/', '', $uri);
        $uri = preg_replace('/^api\//', '/', $uri);
        $uri = preg_replace('/^([\/]*)/', '', $uri);
        $uri = preg_replace('/([\/]*)$/', '', $uri);
        $uri = preg_replace('/([\/]+)/', '_', $uri);

        return strtoupper($uri);
    }

    /**
     * Filter the route by URI and / or name.
     *
     * @param  array $route
     * @return array|null
     */
    protected function filterRoute(array $route)
    {

        return $route;
    }

    /**
     * Get before filters.
     *
     * @param  \Illuminate\Routing\Route $route
     * @return array
     */
    protected function getMiddleware($route)
    {
        return collect($route->gatherMiddleware())->map(function ($middleware) {
            return $middleware instanceof Closure ? 'Closure' : $middleware;
        })->toArray();
    }
}
